Программирование сетевых приложений

Типы исключительных ситуаций и процесс их обработки в C++ и Qt

Программирование сетевых приложений

Содержание лекции

  • Введение в исключительные ситуации
  • Необходимость обработки исключений
  • Основные принципы обработки исключений
  • Типы исключений
  • Обработка исключительных ситуаций
  • Объекты исключительных ситуаций
  • Стандартные исключительные ситуации
  • Пользовательские исключения
  • Особенности обработки исключений в Qt
  • Лучшие практики
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

Введение в исключительные ситуации

Исключительные ситуации (exceptions) являются критически важным механизмом обработки ошибок в современном программировании. Они позволяют разработчикам создавать надежные и устойчивые приложения, способные корректно реагировать на непредвиденные ситуации во время выполнения программы.

Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

Необходимость обработки исключительных ситуаций

Проблемы традиционной обработки ошибок

До появления исключений обработка ошибок в C++ основывалась на следующих подходах:

  1. Коды возврата функций
    int result = someFunction();
    if (result != 0) {
        // Обработка ошибки
    }
    
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений
  1. Глобальные переменные состояния

    errno = 0;
    FILE* file = fopen("data.txt", "r");
    if (errno != 0) {
        // Обработка ошибки
    }
    
  2. Флаги ошибок

    class MyClass {
    private:
        bool errorFlag;
        std::string errorMessage;
    public:
        bool hasError() const { return errorFlag; }
    };
    
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

Преимущества исключений

Исключения решают многие проблемы традиционных подходов:

  1. Разделение кода основной логики и обработки ошибок
  2. Принудительная обработка критических ошибок
  3. Возможность передачи ошибок через несколько уровней стека вызовов
  4. Гарантированная очистка ресурсов (RAII)
  5. Типобезопасность при обработке различных типов ошибок
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

Основные принципы обработки исключений

Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

1. Принцип RAII (Resource Acquisition Is Initialization)

class FileHandler {
private:
    FILE* file;
    
public:
    FileHandler(const std::string& filename) {
        file = fopen(filename.c_str(), "r");
        if (!file) {
            throw std::runtime_error("Не удалось открыть файл");
        }
    }
    
    ~FileHandler() {
        if (file) {
            fclose(file);
        }
    }
    
    // Запрет копирования
    FileHandler(const FileHandler&) = delete;
    FileHandler& operator=(const FileHandler&) = delete;
};
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

2. Принцип безопасности исключений

Базовая гарантия (Basic Guarantee): Программа остается в согласованном состоянии, не происходит утечек ресурсов.

Сильная гарантия (Strong Guarantee): Операция либо завершается успешно, либо оставляет программу в исходном состоянии.

Гарантия отсутствия исключений (No-throw Guarantee): Операция гарантированно не выбрасывает исключений.

Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

3. Принцип специфичности

Обрабатывайте конкретные типы исключений, а не общие:

// Плохо
try {
    // Код
} catch (...) {
    // Слишком общо
}

// Хорошо
try {
    // Код
} catch (const std::invalid_argument& e) {
    // Обработка конкретной ошибки
} catch (const std::out_of_range& e) {
    // Обработка другой конкретной ошибки
}
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

Типы исключений

Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

1. Стандартные исключения C++

Стандартная библиотека C++ предоставляет иерархию исключений:

#include <stdexcept>
#include <iostream>

// Базовый класс для всех стандартных исключений
std::exception
├── std::logic_error
│   ├── std::invalid_argument
│   ├── std::domain_error
│   ├── std::length_error
│   └── std::out_of_range
├── std::runtime_error
│   ├── std::range_error
│   ├── std::overflow_error
│   └── std::underflow_error
└── std::bad_alloc
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

2. Примеры стандартных исключений

#include <stdexcept>
#include <vector>
#include <memory>

void demonstrateStandardExceptions() {
    try {
        // std::invalid_argument
        int parseInt(const std::string& str) {
            if (str.empty()) {
                throw std::invalid_argument("Пустая строка");
            }
            return std::stoi(str);
        }
        
        // std::out_of_range
        std::vector<int> vec = {1, 2, 3};
        int value = vec.at(10); // Выбросит out_of_range
        
        // std::bad_alloc
        try {
            int* hugeArray = new int[1000000000000];
        } catch (const std::bad_alloc& e) {
            std::cerr << "Ошибка выделения памяти: " << e.what() << std::endl;
        }
        
    } catch (const std::exception& e) {
        std::cerr << "Стандартное исключение: " << e.what() << std::endl;
    }
}
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

Обработка исключительных ситуаций

Базовый синтаксис

try {
    // Код, который может выбросить исключение
} catch (const ExceptionType& e) {
    // Обработка исключения типа ExceptionType
} catch (...) {
    // Обработка всех остальных исключений
}
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

Продвинутые техники обработки

1. Повторное выбрасывание исключений

void processData() {
    try {
        // Некоторая обработка
        riskyOperation();
    } catch (const std::exception& e) {
        // Логирование ошибки
        logError(e.what());
        // Повторное выбрасывание для вышестоящей обработки
        throw;
    }
}
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

2. Спецификация исключений (устарело в C++11)

// Старый стиль (не рекомендуется)
void oldStyleFunction() throw(std::runtime_error) {
    // Может выбросить только std::runtime_error
}

// Современный стиль
void modernFunction() noexcept {
    // Гарантированно не выбрасывает исключений
}
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

3. Группировка исключений

template<typename T>
class Container {
public:
    void insert(const T& value) {
        try {
            // Проверка и вставка
            if (value < 0) {
                throw std::invalid_argument("Отрицательное значение");
            }
            if (data_.size() >= max_size_) {
                throw std::length_error("Превышен максимальный размер");
            }
            data_.push_back(value);
        } catch (const std::logic_error& e) {
            // Обработка всех логических ошибок
            std::cerr << "Логическая ошибка: " << e.what() << std::endl;
            throw;
        }
    }
    
private:
    std::vector<T> data_;
    size_t max_size_ = 1000;
};
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

Объекты исключительных ситуаций

Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

Создание собственных классов исключений

#include <string>
#include <chrono>

class NetworkException : public std::runtime_error {
private:
    std::string host_;
    int port_;
    std::chrono::system_clock::time_point timestamp_;
    
public:
    NetworkException(const std::string& message, 
                     const std::string& host, 
                     int port)
        : std::runtime_error(message),
          host_(host),
          port_(port),
          timestamp_(std::chrono::system_clock::now()) {}
    
    const std::string& getHost() const { return host_; }
    int getPort() const { return port_; }
    
    std::chrono::system_clock::time_point getTimestamp() const {
        return timestamp_;
    }
    
    std::string getDetailedMessage() const {
        return what() + std::string(" (") + host_ + ":" + 
               std::to_string(port_) + ")";
    }
};

// Использование
void connectToServer(const std::string& host, int port) {
    // Симуляция ошибки подключения
    bool connectionFailed = true;
    
    if (connectionFailed) {
        throw NetworkException("Не удалось подключиться к серверу", 
                              host, port);
    }
}
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

Иерархия пользовательских исключений

// Базовый класс для всех исключений приложения
class ApplicationException : public std::exception {
protected:
    std::string message_;
    int errorCode_;
    
public:
    ApplicationException(const std::string& message, int errorCode = 0)
        : message_(message), errorCode_(errorCode) {}
    
    const char* what() const noexcept override {
        return message_.c_str();
    }
    
    int getErrorCode() const { return errorCode_; }
};

// Исключения для различных подсистем
class DatabaseException : public ApplicationException {
private:
    std::string query_;
    
public:
    DatabaseException(const std::string& message, 
                     const std::string& query, 
                     int errorCode = 0)
        : ApplicationException(message, errorCode), query_(query) {}
    
    const std::string& getQuery() const { return query_; }
};

class SecurityException : public ApplicationException {
private:
    std::string userId_;
    std::string operation_;
    
public:
    SecurityException(const std::string& message, 
                     const std::string& userId, 
                     const std::string& operation)
        : ApplicationException(message), userId_(userId), operation_(operation) {}
    
    const std::string& getUserId() const { return userId_; }
    const std::string& getOperation() const { return operation_; }
};
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

Стандартные исключительные ситуации

#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>

void demonstrateCommonExceptions() {
    try {
        // std::bad_alloc - нехватка памяти
        try {
            size_t hugeSize = std::numeric_limits<size_t>::max();
            int* array = new int[hugeSize];
        } catch (const std::bad_alloc& e) {
            std::cout << "bad_alloc: " << e.what() << std::endl;
        }
        
        // std::out_of_range
        try {
            std::vector<int> vec = {1, 2, 3};
            int value = vec.at(100); // Выход за границы
        } catch (const std::out_of_range& e) {
            std::cout << "out_of_range: " << e.what() << std::endl;
        }
        
        // std::invalid_argument
        try {
            std::stoi("не число");
        } catch (const std::invalid_argument& e) {
            std::cout << "invalid_argument: " << e.what() << std::endl;
        }
        
        // std::overflow_error
        try {
            int result = std::accumulate(std::vector<int>(1000000, 1000000).begin(),
                                       std::vector<int>(1000000, 1000000).end(), 0);
        } catch (const std::overflow_error& e) {
            std::cout << "overflow_error: " << e.what() << std::endl;
        }
        
    } catch (const std::exception& e) {
        std::cout << "Общее исключение: " << e.what() << std::endl;
    }
}
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

Определение и порождение собственных исключительных ситуаций

Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

Создание иерархии исключений для сетевого приложения

#include <exception>
#include <string>
#include <system_error>

// Базовое исключение для сетевых операций
class NetworkException : public std::runtime_error {
protected:
    int errorCode_;
    std::string details_;
    
public:
    NetworkException(const std::string& message, int errorCode = 0)
        : std::runtime_error(message), errorCode_(errorCode) {}
    
    int getErrorCode() const { return errorCode_; }
    virtual std::string getDetails() const { return what(); }
};

// Исключения для различных сетевых ситуаций
class ConnectionException : public NetworkException {
private:
    std::string host_;
    int port_;
    
public:
    ConnectionException(const std::string& host, int port, int errorCode = 0)
        : NetworkException("Ошибка подключения к " + host + ":" + 
                          std::to_string(port), errorCode),
          host_(host), port_(port) {}
    
    std::string getDetails() const override {
        return "Не удалось подключиться к " + host_ + ":" + 
               std::to_string(port) + " (код ошибки: " + 
               std::to_string(errorCode_) + ")";
    }
};
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений
class DataTransmissionException : public NetworkException {
private:
    size_t bytesSent_;
    size_t bytesTotal_;
    
public:
    DataTransmissionException(size_t sent, size_t total, int errorCode = 0)
        : NetworkException("Ошибка передачи данных", errorCode),
          bytesSent_(sent), bytesTotal_(total) {}
    
    std::string getDetails() const override {
        return "Передано " + std::to_string(bytesSent_) + 
               " из " + std::to_string(bytesTotal_) + 
               " байт (код ошибки: " + std::to_string(errorCode_) + ")";
    }
};

class ProtocolException : public NetworkException {
private:
    std::string protocol_;
    std::string violation_;
    
public:
    ProtocolException(const std::string& protocol, 
                     const std::string& violation, 
                     int errorCode = 0)
        : NetworkException("Нарушение протокола " + protocol, errorCode),
          protocol_(protocol), violation_(violation) {}
    
    std::string getDetails() const override {
        return "Протокол " + protocol_ + ": " + violation_;
    }
};
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

Использование пользовательских исключений

class NetworkClient {
private:
    std::string host_;
    int port_;
    bool connected_;
    
public:
    NetworkClient(const std::string& host, int port)
        : host_(host), port_(port), connected_(false) {}
    
    void connect() {
        try {
            // Симуляция подключения
            bool connectionSuccessful = false; // Симулируем ошибку
            
            if (!connectionSuccessful) {
                throw ConnectionException(host_, port_, 1001);
            }
            
            connected_ = true;
            
        } catch (const ConnectionException& e) {
            std::cerr << "Ошибка подключения: " << e.getDetails() << std::endl;
            // Попытка переподключения или другие действия
            throw;
        }
    }
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений
    void sendData(const std::vector<uint8_t>& data) {
        if (!connected_) {
            throw std::logic_error("Клиент не подключен");
        }
        
        try {
            // Симуляция отправки данных
            size_t sent = 0;
            size_t total = data.size();
            
            // Симулируем частичную отправку с ошибкой
            bool transmissionFailed = true;
            
            if (transmissionFailed) {
                throw DataTransmissionException(sent, total, 2001);
            }
            
        } catch (const DataTransmissionException& e) {
            std::cerr << "Ошибка передачи: " << e.getDetails() << std::endl;
            
            // Попытка восстановления соединения
            try {
                reconnect();
                // Повторная отправка
            } catch (const ConnectionException& reconnectError) {
                std::cerr << "Не удалось восстановить соединение: " 
                         << reconnectError.what() << std::endl;
                throw;
            }
        }
    }
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений
private:
    void reconnect() {
        connected_ = false;
        // Логика переподключения
        connect();
    }
};
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

Особенности обработки исключений в Qt

Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

Использование исключений в Qt-приложениях

#include <QCoreApplication>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QTimer>
#include <QException>
#include <QDebug>

// Qt-ориентированное исключение
class QtNetworkException : public QException {
private:
    QString message_;
    int errorCode_;
    
public:
    QtNetworkException(const QString& message, int errorCode = 0)
        : message_(message), errorCode_(errorCode) {}
    
    void raise() const override { throw *this; }
    QtNetworkException* clone() const override { 
        return new QtNetworkException(*this); 
    }
    
    const char* what() const noexcept override {
        return message_.toLocal8Bit().constData();
    }
    
    QString message() const { return message_; }
    int errorCode() const { return errorCode_; }
};
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений
// Класс для безопасной работы с сетевыми операциями в Qt
class SafeNetworkManager : public QObject {
    Q_OBJECT
    
private:
    QNetworkAccessManager* manager_;
    
public:
    explicit SafeNetworkManager(QObject* parent = nullptr)
        : QObject(parent), manager_(new QNetworkAccessManager(this)) {}
    
    void makeSafeRequest(const QUrl& url) {
        try {
            QNetworkRequest request(url);
            QNetworkReply* reply = manager_->get(request);
            
            // Используем лямбда-функцию для обработки ответа
            connect(reply, &QNetworkReply::finished, [reply, this]() {
                try {
                    handleReply(reply);
                } catch (const QtNetworkException& e) {
                    qWarning() << "Ошибка сети:" << e.message();
                    emit errorOccurred(e.message(), e.errorCode());
                } catch (const std::exception& e) {
                    qWarning() << "Стандартное исключение:" << e.what();
                    emit errorOccurred(QString::fromLocal8Bit(e.what()), -1);
                }
                
                reply->deleteLater();
            });
            
        } catch (const QtNetworkException& e) {
            qWarning() << "Исключение при создании запроса:" << e.message();
            emit errorOccurred(e.message(), e.errorCode());
        }
    }
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений
signals:
    void errorOccurred(const QString& message, int errorCode);
    void dataReceived(const QByteArray& data);
    
private:
    void handleReply(QNetworkReply* reply) {
        if (reply->error() != QNetworkReply::NoError) {
            throw QtNetworkException(
                reply->errorString(), 
                static_cast<int>(reply->error())
            );
        }
        
        QByteArray data = reply->readAll();
        emit dataReceived(data);
    }
};
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

Интеграция исключений с Qt сигналами и слотами

#include <QObject>
#include <QTimer>
#include <QException>

// Класс для демонстрации обработки исключений в Qt событиях
class ExceptionSafeWorker : public QObject {
    Q_OBJECT
    
private:
    QTimer* workTimer_;
    int operationCount_;
    
public:
    explicit ExceptionSafeWorker(QObject* parent = nullptr)
        : QObject(parent), operationCount_(0) {
        
        workTimer_ = new QTimer(this);
        connect(workTimer_, &QTimer::timeout, this, &ExceptionSafeWorker::performWork);
    }
    
    void startWork() {
        workTimer_->start(1000); // Работа каждую секунду
    }
    
    void stopWork() {
        workTimer_->stop();
    }
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений
private slots:
    void performWork() {
        try {
            operationCount_++;
            
            // Симуляция работы с потенциальными исключениями
            if (operationCount_ % 3 == 0) {
                throw std::runtime_error("Симулированная ошибка в работе");
            }
            
            if (operationCount_ % 5 == 0) {
                throw QtNetworkException("Сетевая ошибка в работе", 500);
            }
            
            // Успешная операция
            qDebug() << "Операция" << operationCount_ << "выполнена успешно";
            emit workCompleted(operationCount_);
            
        } catch (const QtNetworkException& e) {
            qWarning() << "Сетевая ошибка в операции" << operationCount_ 
                      << ":" << e.message();
            emit workFailed(operationCount_, e.message());
            
        } catch (const std::exception& e) {
            qWarning() << "Ошибка в операции" << operationCount_ 
                      << ":" << e.what();
            emit workFailed(operationCount_, QString::fromLocal8Bit(e.what()));
            
        } catch (...) {
            qCritical() << "Неизвестная ошибка в операции" << operationCount_;
            emit workFailed(operationCount_, "Неизвестная ошибка");
        }
    }
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений
signals:
    void workCompleted(int operationId);
    void workFailed(int operationId, const QString& error);
};
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

Лучшие практики обработки исключений

Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

1. Использование RAII для управления ресурсами

class DatabaseConnection {
private:
    // Использование умных указателей для автоматического управления ресурсами
    std::unique_ptr<sqlite3, decltype(&sqlite3_close)> db_;
    
public:
    DatabaseConnection(const std::string& dbPath) 
        : db_(nullptr, sqlite3_close) {
        
        sqlite3* rawDb = nullptr;
        int result = sqlite3_open(dbPath.c_str(), &rawDb);
        
        if (result != SQLITE_OK) {
            std::string error = sqlite3_errmsg(rawDb);
            sqlite3_close(rawDb);
            throw std::runtime_error("Не удалось открыть БД: " + error);
        }
        
        db_.reset(rawDb);
    }
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений
    void executeQuery(const std::string& query) {
        char* errorMsg = nullptr;
        int result = sqlite3_exec(db_.get(), query.c_str(), 
                                nullptr, nullptr, &errorMsg);
        
        if (result != SQLITE_OK) {
            std::string error(errorMsg);
            sqlite3_free(errorMsg);
            throw std::runtime_error("Ошибка SQL: " + error);
        }
    }
    
    // Автоматическое закрытие соединения при разрушении объекта
    ~DatabaseConnection() = default;
};
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

2. Создание безопасных интерфейсов

// Безопасный класс для работы с файлами
class SafeFile {
private:
    std::FILE* file_;
    std::string filename_;
    
public:
    SafeFile(const std::string& filename, const std::string& mode)
        : filename_(filename) {
        
        file_ = std::fopen(filename.c_str(), mode.c_str());
        if (!file_) {
            throw std::runtime_error("Не удалось открыть файл: " + filename);
        }
    }
    
    // Запрет копирования
    SafeFile(const SafeFile&) = delete;
    SafeFile& operator=(const SafeFile&) = delete;
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений
    // Разрешение перемещения
    SafeFile(SafeFile&& other) noexcept 
        : file_(other.file_), filename_(std::move(other.filename_)) {
        other.file_ = nullptr;
    }
    
    SafeFile& operator=(SafeFile&& other) noexcept {
        if (this != &other) {
            close();
            file_ = other.file_;
            filename_ = std::move(other.filename_);
            other.file_ = nullptr;
        }
        return *this;
    }
    
    void write(const std::string& data) {
        if (!file_) {
            throw std::logic_error("Файл не открыт");
        }
        
        size_t written = std::fwrite(data.c_str(), 1, data.size(), file_);
        if (written != data.size()) {
            throw std::runtime_error("Ошибка записи в файл");
        }
    }
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений
    std::string read(size_t maxSize = 1024) {
        if (!file_) {
            throw std::logic_error("Файл не открыт");
        }
        
        std::vector<char> buffer(maxSize);
        size_t read = std::fread(buffer.data(), 1, maxSize, file_);
        
        if (std::ferror(file_)) {
            throw std::runtime_error("Ошибка чтения файла");
        }
        
        return std::string(buffer.data(), read);
    }
    
    ~SafeFile() {
        close();
    }
    
private:
    void close() noexcept {
        if (file_) {
            std::fclose(file_);
            file_ = nullptr;
        }
    }
};
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

3. Использование современных возможностей C++

#include <optional>
#include <variant>
#include <expected>

// Использование std::optional для безопасного возврата значений
std::optional<int> safeDivide(int a, int b) {
    if (b == 0) {
        return std::nullopt; // Вместо исключения
    }
    return a / b;
}

// Использование std::variant для возврата различных типов результатов
using Result = std::variant<int, std::string>; // Успех или сообщение об ошибке

Result calculate(int a, int b) {
    if (b == 0) {
        return std::string("Деление на ноль");
    }
    return a / b;
}

// Использование std::expected (C++23)
std::expected<int, std::string> safeCalculation(int a, int b) {
    if (b == 0) {
        return std::unexpected("Деление на ноль");
    }
    return a / b;
}
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

Заключение

Правильная обработка исключений является основой создания надежных и устойчивых приложений на C++. Использование современных подходов, таких как RAII, создание собственных иерархий исключений и интеграция с фреймворками вроде Qt, позволяет создавать качественный код, способный корректно реагировать на непредвиденные ситуации.

Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

Ключевые принципы:

  • Используйте исключения для исключительных ситуаций, а не для обычного потока управления
  • Создавайте специфичные типы исключений для различных типов ошибок
  • Обеспечивайте безопасность исключений через RAII
  • Логируйте исключения для последующего анализа
  • Тестируйте обработку исключений в вашем коде
Типы исключительных ситуаций и процесс их обработки
Программирование сетевых приложений

Вопросы для самопроверки

  1. Какие три уровня гарантии безопасности исключений существуют?
  2. Чем отличается std::logic_error от std::runtime_error?
  3. Как правильно создавать собственные иерархии исключений?
  4. Какие преимущества дает использование RAII в обработке исключений?
  5. Как интегрировать исключения с Qt сигналами и слотами?
  6. Что такое noexcept и когда его следует использовать?
  7. Какие современные альтернативы исключениям доступны в C++?
  8. Как правильно повторно выбрасывать исключения?
Типы исключительных ситуаций и процесс их обработки